<template>
  <el-row :gutter="40">
    <el-col v-if="!form.id">
      <el-empty description="请选择左侧菜单后操作" :image-size="200"></el-empty>
    </el-col>
    <template v-else>
      <el-col :lg="12" class="form">
        <h2>{{ form.meta.title || '新增菜单' }}</h2>
        <el-form :model="form" :rules="rules" ref="formRef" label-width="90px">
          <el-form-item label="显示名称" prop="meta.title">
            <el-input v-model="form.meta.title" clearable placeholder="菜单显示名字"></el-input>
          </el-form-item>
          <el-form-item label="上级菜单" prop="pid">
            <el-cascader
              v-model="form.pid"
              :options="menuOptions"
              :props="menuProps"
              :show-all-levels="false"
              placeholder="顶级菜单"
              clearable
              disabled
            ></el-cascader>
          </el-form-item>
          <el-form-item label="类型" prop="meta.type">
            <el-radio-group v-model="form.meta.type">
              <el-radio-button label="menu">菜单</el-radio-button>
              <el-radio-button label="iframe">iframe</el-radio-button>
              <el-radio-button label="link">外链</el-radio-button>
              <el-radio-button label="button">按钮</el-radio-button>
            </el-radio-group>
          </el-form-item>
          <el-form-item v-show="form.meta.type != 'button'" label="图标" prop="meta.icon">
            <my-icon-select v-model:iconValue="form.meta.icon" clearable></my-icon-select>
          </el-form-item>
          <el-form-item v-show="form.meta.type != 'button'" label="别名" prop="name">
            <el-input v-model="form.name" clearable placeholder="菜单别名"></el-input>
            <div class="el-form-item-msg">系统唯一且与内置组件名一致，否则导致缓存失效</div>
          </el-form-item>
          <el-form-item v-show="form.meta.type != 'button'" label="路由地址" prop="path">
            <el-input v-model="form.path" clearable placeholder="请输入路由地址"></el-input>
          </el-form-item>
          <el-form-item v-show="form.meta.type == 'menu'" label="重定向" prop="redirect">
            <el-input v-model="form.redirect" clearable placeholder=""></el-input>
          </el-form-item>
          <el-form-item v-show="form.pid != 0 && form.meta.type == 'menu'" label="视图" prop="component">
            <el-input v-model="form.component" clearable placeholder="">
              <template #prepend>views</template>
              <template #append>.vue</template>
            </el-input>
            <div class="el-form-item-msg">如父节点、链接、iframe、按钮等没有视图的菜单不需要填写</div>
          </el-form-item>
          <el-form-item label="排序值" prop="sort">
            <el-input v-model="form.meta.sort" clearable></el-input>
            <div class="el-form-item-msg">相同层级数值越小越优先</div>
          </el-form-item>
          <el-form-item v-show="form.meta.type != 'button'" label="是否隐藏">
            <el-checkbox v-model="form.meta.isHidden">隐藏菜单</el-checkbox>
            <div class="el-form-item-msg">菜单不显示在导航中，但用户依然可以访问，例如详情页</div>
          </el-form-item>
          <el-form-item v-show="form.meta.type != 'button'" label="标签" prop="tag">
            <el-input v-model="form.meta.tag" clearable placeholder=""></el-input>
          </el-form-item>
          <el-form-item>
            <el-button type="primary" @click="onSubmit" :loading="loading">保 存</el-button>
          </el-form-item>
        </el-form>
      </el-col>
      <el-col :lg="12" class="api-list">
        <h2>接口权限</h2>
        <my-form-table v-model="form.apiList" :addTemplate="apiListAddTemplate" placeholder="暂无匹配接口权限">
          <el-table-column prop="code" label="标识" width="150">
            <template #default="scope">
              <el-input v-model="scope.row.code" placeholder="请输入内容"></el-input>
            </template>
          </el-table-column>
          <el-table-column prop="url" label="Api url">
            <template #default="scope">
              <el-input v-model="scope.row.url" placeholder="请输入内容"></el-input>
            </template>
          </el-table-column>
        </my-form-table>
      </el-col>
    </template>
  </el-row>
</template>

<script setup lang="ts">
import { ref, reactive } from 'vue'
import type { IMenu } from '@/api/menu/type'
import { MenuApi } from '@/api/menu'
import { CascaderProps, ElForm, ElMessage, FormRules } from 'element-plus'
import MyIconSelect from '@/components/IconSelect/index.vue'
import MyFormTable from '@/components/FormTable/index.vue'
import to from '@/utils/to'

// 简单化菜单
const treeToMap = (tree: IMenu.MenuForm[]): IMenu.SimpleMenu[] => {
  const map: IMenu.SimpleMenu[] = []
  tree.forEach((item: IMenu.MenuForm) => {
    const obj: IMenu.SimpleMenu = {
      id: item.id,
      pid: item.pid,
      title: item.meta.title,
      children: item.children && item.children.length > 0 ? treeToMap(item.children) : null
    }
    map.push(obj)
  })
  return map
}

const props = withDefaults(defineProps<{ menuList: IMenu.MenuForm[] }>(), { menuList: () => [] })

const loading = ref<boolean>(false)
const menuOptions = ref<IMenu.SimpleMenu[]>(treeToMap(props.menuList))
const formRef = ref<InstanceType<typeof ElForm> | null>(null)
const menuProps: CascaderProps = {
  value: 'id',
  label: 'title',
  children: 'children',
  checkStrictly: true
}
// 表单中的菜单树
const form = ref<IMenu.MenuForm>({
  id: 0,
  pid: 0,
  path: '',
  name: '',
  component: '',
  redirect: '',
  meta: {
    type: 'menu',
    icon: '',
    title: '',
    isHidden: false,
    isKeepAlive: true,
    sort: 1000
  },
  apiList: []
})
const apiListAddTemplate = ref({ code: '', url: '' })

const validatorFn = (value: string, callback: Validator.ICallback, msg: string) => {
  if (form.value.meta.type != 'button' && value == '') {
    return callback(new Error(msg))
  }
  callback()
}
// 验证规则
const rules = reactive<FormRules<Omit<IMenu.MenuForm, 'children'>>>({
  id: [{ required: true, message: '主键异常请刷新页面', trigger: 'blur' }],
  pid: [],
  path: [
    {
      required: true,
      validator: (_, value: string, callback: Validator.ICallback) => validatorFn(value, callback, '请输入路由地址'),
      trigger: ['blur']
    }
  ],
  name: [
    {
      required: true,
      validator: (_, value: string, callback: Validator.ICallback) => validatorFn(value, callback, '请输入路由别名'),
      trigger: ['blur']
    }
  ],
  component: [
    {
      required: true,
      validator: (_: object, value: string, callback: Validator.ICallback) => {
        if (form.value.pid != 0 && form.value.meta.type != 'menu' && value == '') {
          return callback(new Error('请输入视图'))
        }
        callback()
      },
      trigger: ['blur']
    }
  ],
  'meta.type': [{ required: true, message: '请选择菜单类型', trigger: 'blur' }],
  'meta.title': [{ required: true, message: '请输入显示名称', trigger: 'blur' }],
  'meta.icon': [
    {
      required: true,
      validator: (_, value: string, callback: Validator.ICallback) => validatorFn(value, callback, '请选择菜单图标'),
      trigger: ['blur', 'change']
    }
  ],
  'meta.sort': [{ required: true, type: 'integer', message: '排序值只能为数值', trigger: 'blur' }]
})

//表单注入数据
const setData = (data: IMenu.MenuForm) => (form.value = data)
defineExpose({ setData })
// 编辑提交
const onSubmit = async () => {
  try {
    if (await to(formRef.value?.validate())) return
    loading.value = true
    await MenuApi.edit(form.value)
    ElMessage.success('菜单编辑成功')
  } finally {
    loading.value = false
  }
}
</script>

<style scoped>
h2 {
  font-size: 17px;
  color: #3c4a54;
  padding: 0 0 30px 0;
}
.api-list {
  border-left: 1px solid var(--el-border-color-light);
}

[data-theme='dark'] h2 {
  color: #fff;
}
[data-theme='dark'] .api-list {
  border-color: #434343;
}
</style>
